#include "mainwindow.h"
#include <QApplication>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/wait.h>
typedef struct shmpid{
    int pid_1;
    int pid_2;
}PID; // 使用共享内存记录子进程id
char fifo_name[] = "myfifo"; // 有名管道名称
int main(int argc, char *argv[])
{
    // 获取键值
    key_t key;
    if((key = ftok("/", 2024)) == -1)
    {
        perror("ftok");
        return 0;
    }
    // 创建一个共享内存
    int shm_id;
    if((shm_id = shmget(key, sizeof(shmpid), IPC_CREAT | 0666)) == -1)
    {
        perror("shmget");
        return 0;
    }
    // 映射共享内存的地址
    PID *addr;
    if((addr = (PID *)shmat(shm_id, NULL, 0)) == (PID*)-1)
    {
        perror("shmat");
        return 0;
    }

    // 创建无名管道 用于读取mplayer返回内容
    int fd[2];
    if(pipe(fd) == -1)
    {
        perror("pipe");
        return 0;
    }
    // 创建有名管道
    mkfifo(fifo_name, 0666);

    // 创建子进程
    int i=0;
    pid_t pid;
    for(; i < 2;i++)
    {
        pid = fork();
        if(pid < 0)
        {
            perror("fork");
            _exit(0);
        }else if(pid == 0)
            break;
    }
    if(i == 0) // 第一个子进程用来给mplayer发送指令
    {
        // 共享内存 记录子进程id
        addr->pid_1 = getpid();

        // 将标准输出重定向到无名管道的输入
        dup2(fd[1], 1);

        // 使用exec执行mplayer
        char *avg[] = {"mplayer", "-slave","-quiet","-idle","-input", "file=./myfifo", NULL};
        execvp("mplayer", avg);
//        execlp("mplayer", "mplayer", "-slave","-quiet","-idle","-input", "file=./myfifo",NULL);
        return 0;
    }
    else if(i == 1) // 第二个子进程用来执行qt
    {
        // 共享内存 记录子进程id
        addr->pid_2 = getpid();

        QApplication a(argc, argv);
        MainWindow w(fd[0], fifo_name); // 需要获取mplayer返回的数据, 添加一个入参
        w.show();
        return a.exec();
    }
    else if(i == 2) // 主进程监听qt程序是否结束
    {
        while(1)
        {
            int ret = waitpid(-1 ,NULL,WNOHANG); // 不阻塞
            if(ret == 0) // 还有子进程在运行,且没有子进程退出
                continue;
            else if(ret > 0)
            {
                if(ret == addr->pid_2) // 如果是qt进程退出则关闭mplayer
                {
                    kill(addr->pid_1, SIGKILL);
                }
            }
            else if(ret == -1) // 子进程都退出了
                break;
        }
        // 子进程都退出后删除fifo管道文件
        unlink(fifo_name);
        // 释放映射链接
        shmdt(addr);
        // 删除共享内存段
        shmctl(shm_id, IPC_RMID, NULL);
    }

    return 0;
}
